import numpy as np
from scipy.stats import entropy
from math import log, e
import pandas as pd
import time

import timeit

def entropy1(labels, base=None):
  value,counts = np.unique(labels, return_counts=True)
  return entropy(counts, base=base)

def entropy2(labels, base=None):
  """ Computes entropy of label distribution. """

  n_labels = len(labels)

  if n_labels <= 1:
    return 0

  value,counts = np.unique(labels, return_counts=True)
  probs = counts / n_labels
  n_classes = np.count_nonzero(probs)

#   print(probs)

  if n_classes <= 1:
    return 0

  ent = 0.

  # Compute entropy
  base = e if base is None else base
  for i in probs:
    ent -= i * log(i, base)

  return ent

def entropy3(labels, base=None):
  vc = pd.Series(labels).value_counts(normalize=True, sort=False)
  base = e if base is None else base
  return -(vc * np.log(vc)/np.log(base)).sum()

def entropy4(labels, base=None):
  value,counts = np.unique(labels, return_counts=True)
  norm_counts = counts / counts.sum()
  base = e if base is None else base
  return -(norm_counts * np.log(norm_counts)/np.log(base)).sum()

labels = [1,3,5,2,3,5,3,2,1,3,4,5]

start = time.time()
et1 = entropy1(labels)
t1 = time.time() - start
start = time.time()
et2 = entropy2(labels)
t2 = time.time() - start
start = time.time()
et3 = entropy3(labels)
t3 = time.time() - start
start = time.time()
et4 = entropy4(labels)
t4 = time.time() - start

print(et1)
print(et2)
print(et3)
print(et4)

# print times
print("entropy1:", t1*1000)
print("entropy2:", t2*1000)
print("entropy3:", t3*1000)
print("entropy4:", t4*1000)
